package com.jzg.sys.manager;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzg.sys.api.sec.MenuService;
import com.jzg.sys.common.util.CommonUtils;
import com.jzg.sys.dao.entity.SecMenu;
import com.jzg.sys.dao.entity.SecResource;
import com.jzg.sys.dao.entity.SecRoleMenu;
import com.jzg.sys.dao.entity.SecUserRole;
import com.jzg.sys.dao.mapper.SecMenuMapper;
import com.jzg.sys.dao.mapper.SecResourceMapper;
import com.jzg.sys.dao.mapper.SecRoleMenuMapper;
import com.jzg.sys.dao.mapper.SecUserRoleMapper;
import com.jzg.sys.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 菜单 服务实现类
 * </p>
 *
 * @author lzp
 * @since 2019-02-22
 */
@Service("menuService")
public class SecMenuManager extends ServiceImpl<SecMenuMapper, SecMenu> implements MenuService {
    @Resource
    private SecMenuMapper menuDao;
    @Resource
    private SecUserRoleMapper userRoleDao;
    @Resource
    private SecRoleMenuMapper roleMenuMapper;
    @Resource
    private SecResourceMapper resourceMapper;

    public List<SecMenu> findMenuAllTreeWithRole(String userId, String sysCode) {
        // 超级管理员
        if ("1".equals(userId)) {
            return findMenuTreeNoRole(null, sysCode);
        }
        List<SecUserRole> userRoles = userRoleDao.selectList(new QueryWrapper<SecUserRole>().
                lambda()
                .eq(SecUserRole::getUserId, userId)
        );
        String roleId = null;
        if (userRoles != null && !userRoles.isEmpty()) {
            roleId = userRoles.get(0).getRoleId();
        } else {// 返回空
            return new ArrayList<SecMenu>();
        }
        SecMenu menu = new SecMenu();
        menu.setMenuId(null);
        menu.setRoleId(roleId);
        menu.setUserId(userId);
        menu.setSysCode(sysCode);
        List<SecMenu> menus = menuDao.findMenuTreeWithRole(menu);
        findChildrenWithRole(menus, roleId, userId, sysCode);
        return menus;
    }

    /**
     * @param menuId
     * @return
     * @Title: findMenuTreeNoRole
     * @Description: 超级管理员无需权限
     * @author 李志鹏 lzp
     * @date 2016年6月30日 上午10:40:02
     */
    private List<SecMenu> findMenuTreeNoRole(String menuId, String sysCode) {
        SecRoleMenu roleMenu = new SecRoleMenu();
        roleMenu.setMenuId(menuId == null ? "" : menuId);
        List<SecMenu> menus = menuDao.selectList(new QueryWrapper<SecMenu>()
                .lambda()
                .eq(SecMenu::getSysCode, sysCode)
                .and(w -> w.isNull(SecMenu::getParentId)
                        .or()
                        .eq(SecMenu::getParentId, ""))
                .eq(StringUtils.isNotEmpty(menuId), SecMenu::getParentId, menuId)
                .orderByAsc(SecMenu::getMenuCode));
        findChildren(menus);
        return menus;
    }

    private void findChildren(List<SecMenu> menus) {
        for (SecMenu secMenu : menus) {
            List<SecMenu> children = menuDao.selectList(new QueryWrapper<SecMenu>()
                    .lambda()
                    .eq(SecMenu::getParentId, secMenu.getMenuId())
                    .orderByAsc(SecMenu::getMenuCode));
            secMenu.setChildren(children);
        }
    }

    /**
     * @param menus
     * @param roleId
     * @param userId
     * @param sysCode
     * @return
     * @Title: findChildrenWithRole
     * @Description: 查询有权限的子菜单
     * @Author: lzp 李志鵬
     * @Date: 2019/3/7
     */
    private void findChildrenWithRole(List<SecMenu> menus, String roleId, String userId, String sysCode) {
        for (SecMenu secMenu : menus) {
            secMenu.setUserId(userId);
            secMenu.setRoleId(roleId);
            secMenu.setSysCode(sysCode);
            List<SecMenu> children = menuDao.findMenuTreeWithRole(secMenu);
            secMenu.setChildren(children);
        }
    }

    /**
     * @param parentId
     * @param sysCode
     * @return
     * @Title: findMenuTree
     * @Description: 异步查询菜单树
     * @Author: lzp 李志鵬
     * @Date: 2019/3/7
     */
    public List<SecMenu> findMenuTree(String parentId, String sysCode) {
        List<SecMenu> list =
                menuDao.selectList(new QueryWrapper<SecMenu>()
                        .lambda()
                        .eq(SecMenu::getSysCode, sysCode)
                        .eq(StringUtils.isNotEmpty(parentId), SecMenu::getParentId, parentId)
                        .and(StringUtils.isEmpty(parentId), w -> w.isNull(SecMenu::getParentId)
                                .or()
                                .eq(SecMenu::getParentId, ""))
                        .orderByAsc(SecMenu::getMenuCode)
                );
        list.forEach(secMenu -> {
            secMenu.setChildSize(menuDao.selectCount(new QueryWrapper<SecMenu>()
                    .lambda()
                    .eq(SecMenu::getParentId, secMenu.getMenuId())
            ));
            if (StringUtils.isEmpty(parentId)) {
                secMenu.setTreeLevel(1);
            } else {
                secMenu.setTreeLevel(2);
            }
        });
        return list;
    }

    /**
     * @param menuId
     * @return
     * @Title: delMenu
     * @Description: 删除菜单
     * 1.菜单已被使用，不允许删除
     * 2.删除菜单和资源
     * 3.仅删除菜单
     * @Author: lzp 李志鵬
     * @Date: 2019/3/5
     */
    public void delMenu(String menuId) {
        SecMenu menu = menuDao.selectById(menuId);
        int c = roleMenuMapper.selectCount(new QueryWrapper<SecRoleMenu>().lambda()
                .eq(SecRoleMenu::getMenuId, menuId)
        );
        if (c > 0) {
            throw new BusinessException("菜单已被用户使用，不允许删除");
        }
        //资源是否被多用
        if (isUseMulti(menuId)) {//仅删除菜单
            menuDao.deleteById(menuId);
        } else {
            //删除资源
            resourceMapper.delete(new UpdateWrapper<SecResource>().lambda()
                    .eq(SecResource::getMenuId, menuId)
            );
            //删除菜单
            menuDao.deleteById(menuId);
        }
        if (StringUtils.isNotBlank(menu.getParentId())) {
            int count = menuDao.selectCount(new QueryWrapper<SecMenu>().lambda()
                    .eq(SecMenu::getParentId, menu.getParentId())
            );
            if (count == 0) {//将父菜单改为叶子
                SecMenu parent = menuDao.selectById(menu.getParentId());
                parent.setIsLeaf(false);
                menuDao.updateById(parent);
            }
        }
    }

    /**
     * @param menuId
     * @return
     * @Title: isUseMulti
     * @Description: 菜单对应资源是否被多用
     * @Author: lzp 李志鵬
     * @Date: 2019/3/5
     */
    public boolean isUseMulti(String menuId) {
        SecResource resource = resourceMapper.selectOne(new QueryWrapper<SecResource>().lambda()
                .eq(SecResource::getMenuId, menuId)
        );
        if (resource == null)
            return false;
        int c = menuDao.selectCount(new QueryWrapper<SecMenu>().lambda()
                .eq(SecMenu::getResourceId, resource.getResourceId())
        );
        return c > 1;
    }

    /**
     * @param secMenu
     * @return
     * @Title: insertMenu
     * @Description: 新增菜单
     * @Author: lzp 李志鵬
     * @Date: 2019/3/5
     */
    public void insertMenu(SecMenu secMenu) {
        secMenu.setMenuId(secMenu.getMenuId().replace("new", ""));
        if (StringUtils.isNotBlank(secMenu.getMenuUrl())) {//保存或沿用资源
            String actionName = secMenu.getMenuUrl();
            if (actionName.indexOf("/") > 0) {
                actionName = actionName.substring(0, actionName.indexOf("/"));
            }
            SecResource resource = resourceMapper.selectOne(new QueryWrapper<SecResource>().lambda()
                    .eq(SecResource::getResourceContent, "/" + actionName + "/**")
                    .eq(SecResource::getSysCode, secMenu.getSysCode())
            );
            if (resource == null) {
                resource = new SecResource();
                resource.setResourceId(CommonUtils.getUUID());
                resource.setMenuId(secMenu.getMenuId());
                resource.setResourceCode(actionName);
                resource.setResourceContent("/" + actionName + "/**");
                resource.setResourceType("01");
                resource.setSysCode(secMenu.getSysCode());
                resource.setIsValid(true);
                resourceMapper.insert(resource);
            }
            secMenu.setResourceId(resource.getResourceId());
        }
        menuDao.insert(secMenu);
        if (StringUtils.isNotBlank(secMenu.getParentId())) {//将父菜单改为叶子
            SecMenu parent = menuDao.selectById(secMenu.getParentId());
            parent.setIsLeaf(false);
            menuDao.updateById(parent);
        }
    }

    /**
     * @param sysCode
     * @return
     * @Title: findMenuAllTree
     * @Description: 同步查询所有菜单树
     * @Author: lzp 李志鵬
     * @Date: 2019/3/7
     */
    public List<SecMenu> findMenuAllTree(String sysCode) {
        List<SecMenu> menus = menuDao.selectList(new QueryWrapper<SecMenu>()
                .lambda()
                .eq(SecMenu::getSysCode, sysCode)
                .isNull(SecMenu::getParentId)
                .orderByAsc(SecMenu::getMenuCode));
        findChildren(menus);
        return menus;
    }
}
